package zhaomh.zhlib.gui.screen;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.PressableWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.text.Text;
import zhaomh.zhlib.ModInstance;
import zhaomh.zhlib.config.EnumValue;
import zhaomh.zhlib.config.ToggleValue;
import zhaomh.zhlib.config.Value;
import zhaomh.zhlib.gui.widget.ConfigWidget;
import zhaomh.zhlib.gui.widget.EnumConfigWidget;
import zhaomh.zhlib.gui.widget.ToggleConfigWidget;
import zhaomh.zhlib.util.PinyinUtil;
import zhaomh.zhlib.util.PositionUtil;
import zhaomh.zhlib.util.TextUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ConfigScreen extends Screen implements ModInstance {
    private final List<String> types;
    private final Map<String, ButtonWidget> typeButtonWidgets = new HashMap<>();
    private final int spacing = 15;
    private Map<String, List<ConfigWidget<? extends Value>>> valueMap;
    private TextFieldWidget searchWidget;
    private List<ConfigWidget<? extends Value>> renderWidgets;
    private String currentType;
    private final ButtonWidget.PressAction pressAction = button -> {
        String message = button.getMessage().getString();
        for (String type : valueMap.keySet()) {
            if (TextUtil.Translatable(type).getString().equals(message)) {
                currentType = type;
                if (searchWidget.getText().isEmpty())
                    renderWidgets = valueMap.get(currentType);
                else
                    renderWidgets = searchWidgets(valueMap.get(currentType), searchWidget.getText());
                reloadWidgets();
            }
        }
    };

    private ConfigScreen(Map<String, List<ConfigWidget<? extends Value>>> valueMap, List<String> types) {
        super(Text.of("ConfigScreen"));
        this.valueMap = valueMap;
        this.types = types;
        currentType = valueMap.keySet().toArray()[0].toString();
        renderWidgets = valueMap.get(currentType);
        test();
    }

    private void test() {
        for (String s : valueMap.keySet()) {
            for (ConfigWidget<? extends Value> widget : valueMap.get(s)) {
                widget.getValue().addListener((v)->{
                    System.out.println("renderWidgets: ");
                    for (ConfigWidget<? extends Value> renderWidget : renderWidgets) {
                        System.out.println(renderWidget.getValue().getName());
                    }
                    System.out.println("currentType: "+currentType);
                });
            }
        }
    }

    public static Builder builder(List<String> types) {
        return new Builder(types);
    }

    @Override
    protected void init() {
        addWidgets();
        reloadWidgets();
    }

    private void reloadWidgets() {
        searchWidget.setPosition(spacing, spacing);

        int i = 0;
        for (String type : types) {
            typeButtonWidgets.get(type).setPosition(spacing + i * (spacing + 120), spacing + 20 + spacing);
            int j = 0;
            int maxWidth = 200;
            for (ConfigWidget<? extends Value> w : valueMap.get(type)) {
                ((PressableWidget) w).setPosition(spacing, spacing + 20 + spacing + 20 + spacing + j * (20 + spacing));
                ((PressableWidget) w).visible = false;
                maxWidth = Math.max(maxWidth, mc.textRenderer.getWidth(w.getValue().getTrName()));
                j++;
            }
            for (ConfigWidget<? extends Value> w : valueMap.get(type)) {
                ((PressableWidget) w).setX(spacing + maxWidth + 8);
            }
            i++;
        }

        i = 0;
        int maxWidth = 200;
        for (ConfigWidget<? extends Value> w : renderWidgets) {
            ((PressableWidget) w).setPosition(spacing, spacing + 20 + spacing + 20 + spacing + i * (20 + spacing));
            ((PressableWidget) w).visible = true;
            maxWidth = Math.max(maxWidth, mc.textRenderer.getWidth(w.getValue().getTrName()));
            i++;
        }

        for (ConfigWidget<? extends Value> w : renderWidgets) {
            ((PressableWidget) w).setX(spacing + maxWidth + 8);
        }
    }

    private List<ConfigWidget<? extends Value>> searchWidgets(List<ConfigWidget<? extends Value>> configWidgets,String text) {
        return configWidgets.stream().filter(configWidget -> PinyinUtil.contains(configWidget.getValue().getTrName(), text)).toList();
    }

    private void addWidgets() {
        searchWidget = new TextFieldWidget(mc.textRenderer, spacing, spacing, 120, 20, Text.of(""));
        searchWidget.setChangedListener((text)->{
            if (text.isEmpty())
                renderWidgets = valueMap.get(currentType);
            else
                renderWidgets = searchWidgets(valueMap.get(currentType), text);
            reloadWidgets();
        });
        addDrawableChild(searchWidget);

        for (String type : types) {
            ButtonWidget buttonWidget = ButtonWidget.builder(TextUtil.Translatable(type), pressAction).size(120, 20).build();
            addDrawableChild(buttonWidget);
            typeButtonWidgets.put(type, buttonWidget);
            int maxWidth = 200;
            for (ConfigWidget<? extends Value> w : valueMap.get(type)) {
                addDrawableChild(w);
                maxWidth = Math.max(maxWidth, mc.textRenderer.getWidth(w.getValue().getTrName()));
                ((PressableWidget) w).setX(spacing + maxWidth + 8);
            }
        }
    }

    @Override
    public void render(DrawContext context, int mouseX, int mouseY, float delta) {
        super.render(context, mouseX, mouseY, delta);
        for (ConfigWidget<? extends Value> widget : renderWidgets) {
            String name = widget.getValue().getTrName();
            PressableWidget pWidget =(PressableWidget) widget;
            context.drawText(mc.textRenderer, name, spacing + 3, pWidget.getY() + (pWidget.getHeight() - mc.textRenderer.fontHeight) / 2, -1, true);
            if (PositionUtil.inBox(mouseX,mouseY,spacing,pWidget.getY(),pWidget.getX()-spacing-2,pWidget.getHeight())) {
                setTooltip(Text.of(widget.getValue().getDescription()));
            }
        }
    }

    @Environment(EnvType.CLIENT)
    public static class Builder {
        private final Map<String, List<ConfigWidget<? extends Value>>> valueMap = new HashMap<>();
        private final List<String> types;

        public Builder(List<String> types) {
            this.types = types;
            for (String type : types) {
                valueMap.put(type, new ArrayList<>());
            }
        }

        public Builder addValue(Value value, String type) {
            if (value instanceof ToggleValue toggleValue)
                valueMap.get(type).add(ToggleConfigWidget.builder(toggleValue).build());

            else if (value instanceof EnumValue enumValue)
                valueMap.get(type).add(EnumConfigWidget.builder(enumValue).build());

            return this;
        }

        public ConfigScreen build() {
            return new ConfigScreen(valueMap, types);
        }
    }
}
